
package com.tdcy.framework.util;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.tdcy.framework.exception.BaseException;

/**
 * XML公用函数包。
 */
public class XMLFunc {
	/**
	 * 转换XML字符串到XML document.
	 * 
	 */
	public static Document getXMLDocFromStr(final String strXml)
			throws BaseException {
		// 创建DocumentBuilder对象
		DocumentBuilderFactory dbf = null;
		DocumentBuilder db = null;
		dbf = DocumentBuilderFactory.newInstance();
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			System.err.println(pce);
			return (null);
		}

		// 通过字符串得到Document对象
		Document doc = null;
		Reader sr = new StringReader(strXml);
		InputSource is = new InputSource(sr);
		try {
			doc = db.parse(is);
		} catch (SAXException se) {
			throw new BaseException("SAX解析XML串时出错。", se);
		} catch (IOException ioe) {
			throw new BaseException("解析XML串时出现IO异常。", ioe);
		}
		return doc;
	}

	/**
	 * 转换XML document到字符串
	 * 
	 */
	public static String getStrFromDoc(final Document docXml)
			throws BaseException {
		DOMSource domSource = new DOMSource(docXml);
		StringWriter out = new StringWriter();
		StreamResult streamResult = new StreamResult(out);
		TransformerFactory tf = TransformerFactory.newInstance();
		try {
			Transformer transformer = tf.newTransformer();
			// transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT,
			// "yes");
			transformer.setOutputProperty(
					javax.xml.transform.OutputKeys.METHOD, "xml");
			// transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING,
			// "ISO8859-1");
			transformer.transform(domSource, streamResult);
		} catch (TransformerConfigurationException tce) {
			throw new BaseException("转换XML Document时出现配置异常。", tce);
		} catch (TransformerException te) {
			throw new BaseException("转换XML Document时出现转换异常。", te);
		} catch (IllegalArgumentException ie) {
			throw new BaseException("转换XML Document时出现参数设置异常。", ie);
		}

		out.flush();
		return out.toString();

		/*
		 * String str = new String(); System.out.println(new Date()); str =
		 * pr_transform.TreeWalk(docXml); System.out.println(new Date()); return
		 * str;
		 */
	}

	/**
	 * 从本地的XML文件生成XML Document
	 * 
	 */
	public static Document getXMLDocFromFile(final String strFileName)
			throws BaseException {
		// 创建DocumentBuilder对象
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			System.err.println(pce);
			return (null);
		}

		// 通过字符串得到Document对象
		Document doc = null;
		try {
			doc = db.parse(new File(strFileName));
		} catch (SAXException se) {
			throw new BaseException("SAX解析XML串时出错。", se);
		} catch (IOException ioe) {
			throw new BaseException("解析XML串时出现IO异常。", ioe);
		}
		return doc;
	}

	/**
	 * 创建一个出口XML Document框架，将FunctionID、ErrorID、
	 * ErrorMessage、Exception四个必要元素加入到文档中。
	 * 
	 */
	public static Document createNewDocument(final int errno,
			final String strerr,
			final String excep) throws BaseException {
		Element e1, e2;
		Text e4;
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;

		// 创建Document对象
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException pce) {
			throw new BaseException("创建XML生成器时出现异常。", pce);
		}
		Document docnew = db.newDocument();

		// 生成框架及加入必要元素
		try {
			e1 = docnew.createElement("Program");

			e2 = docnew.createElement("ErrorNo");
			e4 = docnew.createTextNode(String.valueOf(errno));
			e2.appendChild(e4);
			e1.appendChild(e2);

			if (strerr != null) {
				e2 = docnew.createElement("ErrorMessage");
				e4 = docnew.createTextNode(strerr);
				e2.appendChild(e4);
				e1.appendChild(e2);
			}

			if (excep != null) {
				e2 = docnew.createElement("Exception");
				e4 = docnew.createTextNode(excep);
				e2.appendChild(e4);
				e1.appendChild(e2);
			}

			docnew.appendChild(e1);
		} catch (DOMException e) {
			throw new BaseException("将信息加到XML Document中时出错异常。", e);
		}

		return docnew;
	}

	/**
	 * 将XML的标记字符和实体引用相互转换
	 * 
	 * @param strValue
	 *            要转换的字符串
	 * @param iFlag
	 *            转换标志，1：XML的标记字符转换成实体引用 2：实体引用还原
	 * @return 转换的StringBuffer
	 */
	public static StringBuffer transMarkupChar(final String strValue,
			final int iFlag) { // LXHua-XML
		if (strValue == null)
			return new StringBuffer("");
		String strTransString = "";
		// 不用hashtable，是因为要按顺序转换
		String strMarkupCharArray[] = { "&", ">", "<", "\"", "'" };
		String strEntityCharArray[] = { "&amp;", "&gt;", "&lt;", "&quot;",
				"&apos;" };
		String strMarkupChar = "", strEntityChar = "";
		strTransString = strValue;
		for (int i = 0; i < strMarkupCharArray.length; i++) {
			strMarkupChar = strMarkupCharArray[i];
			strEntityChar = strEntityCharArray[i];
			if (iFlag == 1) {
				strTransString = strTransString.replaceAll(strMarkupChar,
						strEntityChar);
			} else {
				strTransString = strTransString.replaceAll(strEntityChar,
						strMarkupChar);
			}
		}
		return new StringBuffer(strTransString);
	}

	/**
	 * 根据标签分隔XML字符串.
	 * 
	 * @param str
	 *            XML字符串
	 * @param tag
	 *            分割标签
	 * 
	 * @return 分割后的字符串数组
	 * 
	 * @throws BaseException
	 *             the hygeia exception
	 */
	public static List splitXMLString(final String str, final String tag)
			throws BaseException {
		if (StringUtils.isEmpty(str) || StringUtils.isEmpty(tag)) {
			throw new BaseException("分隔XML串或者分隔符不能为空");
		}

		List lst = new ArrayList();
		int len = str.length();
		int beginPos = 0, endPos = 0;
		do {
			beginPos = str.indexOf("<" + tag + ">", endPos);
			if (beginPos < 0) {
				break;
			}

			endPos = str.indexOf("</" + tag + ">", beginPos);
			if (endPos < 0) {
				throw new BaseException("XML串没有" + tag + "结束标记");
			}
			endPos += (tag.length() + 3);
			lst.add(str.substring(beginPos, endPos));

		} while (endPos < len);

		return lst;
	}

	/**
	 * 根据标签获取XML元素值.
	 * 
	 * @param str
	 *            XML字符串
	 * @param tag
	 *            分割标签
	 * 
	 * @return XML元素值
	 * 
	 * @throws BaseException
	 *             the hygeia exception
	 */
	public static String getXMLElementValue(final String str, final String tag)
			throws BaseException {
		if (StringUtils.isEmpty(str) || StringUtils.isEmpty(tag)) {
			return null;
		}

		String val = null;
		int beginPos = 0, endPos = 0;
		beginPos = str.indexOf("<" + tag + ">", endPos);
		if (beginPos >= 0) {
			endPos = str.indexOf("</" + tag + ">", beginPos);
			if (endPos >= 0) {
				val = str.substring(beginPos + tag.length() + 2, endPos);
			}
		}

		return val;
	}
}
